package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jsola.admin.constant.TaskSubjectResultEnum;
import org.jsola.admin.entity.AsyncTaskDetailDO;
import org.jsola.admin.service.IAsyncTaskDetailService;
import org.jsola.admin.service.IAsyncTaskService;
import org.jsola.contract.constant.AccountType;
import org.jsola.contract.constant.SignMethod;
import org.jsola.contract.entity.AccountDO;
import org.jsola.contract.entity.ContractDO;
import org.jsola.contract.entity.SealPositionDO;
import org.jsola.contract.vo.CategoryVO;
import org.jsola.contract.vo.SealVO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.JunZiQianUtil;
import org.jsola.hr.constant.JunZiQianConstants;
import org.jsola.hr.core.JunZiQianProperties;
import org.jsola.hr.provider.IContractProviderService;
import org.jsola.hr.service.ICompanyContractQuotaService;
import org.jsola.hr.vo.CompanyContractQuotaVO;
import org.jsola.hr.vo.junziqian.PositionVO;
import org.jsola.hr.vo.junziqian.SignAddVO;
import org.jsola.hr.vo.junziqian.SignatoryVO;
import org.jsola.json.JsonKit;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ContractAsync {

    @Autowired
    private IAsyncTaskDetailService asyncTaskDetailService;

    @Autowired
    private IAsyncTaskService asyncTaskService;

    @Autowired
    private IContractProviderService contractProviderService;

    @Autowired
    private ICompanyContractQuotaService companyContractQuotaService;

    @Autowired
    private JunZiQianProperties junZiQianProperties;

    public void contractSignAgainAsync(Long contractId, String companyId, TokenUser tokenUser, String taskId,
                                       CountDownLatch countDownLatch) {
        long time = System.currentTimeMillis();
        AsyncTaskDetailDO asyncTaskDetailDO = new AsyncTaskDetailDO();
        asyncTaskDetailDO.setTaskId(taskId);
        asyncTaskDetailDO.setSubjectId(String.valueOf(contractId));
        log.info("线程名称：{},异步公司签署合同,合同id：{}", Thread.currentThread().getName(), contractId);
        try {
            // 模拟一下子任务
//            Thread.sleep((int)(Math.random()*5+1)*1000);
            companySignAdd(contractId, tokenUser);
//            signService.contractSignAgain(contractId, companyId, tokenUser);
            // 完成一个子任务，记录一下
            asyncTaskDetailDO.setSubjectResult(TaskSubjectResultEnum.SUCCESS.getValue());
        } catch (Exception e) {
            log.error("线程名称：{},异步发起合同异常,名称{}，用时：{}, 异常", Thread.currentThread().getName(), contractId, System.currentTimeMillis() - time, e);
            log.error("异步调用公司合同签署异常：", e);
            asyncTaskDetailDO.setSubjectResult(TaskSubjectResultEnum.FAIL.getValue());
            asyncTaskDetailDO.setErrorMessage(e.getMessage());
            asyncTaskService.taskFail(taskId);
        } finally {
            asyncTaskDetailService.save(asyncTaskDetailDO, tokenUser.getSiteId(), tokenUser.getUserId());
            asyncTaskService.finishSubTask(taskId);
            countDownLatch.countDown();
            log.info("线程名称：{},异步发起合同结束,合同id{}，用时：{}", Thread.currentThread().getName(), contractId, System.currentTimeMillis() - time);
        }
    }

    /**
     * 企业追加签署
     */
    private void companySignAdd(Long contractId, TokenUser tokenUser) {
        ContractDO contractDO = contractProviderService.selectById(contractId);
        SignAddVO vo = new SignAddVO();
        vo.setApplyNo(contractDO.getContractNo());
        vo.setIsArchive(1);
        vo.setPositionType(0);
        CategoryVO category = contractProviderService.selectCategoryById(contractDO.getCategoryId(), tokenUser.getSiteId());
        // 企业单方签署不需要确认签署，等待君子签回调处理即可
        ParamException.isFalse(SignMethod.ENTERPRISE_ONLY.getValue().equals(category.getSignType()),
                "企业单方签署无需确认签署");

        SealVO sealVO = contractProviderService.selectSealById(category.getEnterpriseSealId(), tokenUser.getSiteId());
        CompanyContractQuotaVO quotaVO = companyContractQuotaService.selectById(sealVO.getOrganizationId(), tokenUser.getSiteId());

        // 可以优化accountDO为使用quotaVO的信息
        AccountDO accountDO = contractProviderService.findAccount(AccountType.ENTERPRISE, String.valueOf(quotaVO.getId()));
        SignatoryVO sign = new SignatoryVO();
        sign.setServerCaAuto(1);
        sign.setSignLevel(1);
        sign.setFullName(accountDO.getName());
        sign.setIdentityType(12);
        sign.setOrderNum(2);
        sign.setEmail(accountDO.getAccountId());
        sign.setIdentityCard(accountDO.getOrganCode());
        sign.setSignId(Long.valueOf(sealVO.getThirdSealId()));
        List<SealPositionDO> positionDOS = contractProviderService.selectByContractId(contractDO.getId(), tokenUser);
        Map<Integer, List<SealPositionDO>> map = positionDOS.stream().collect(Collectors.groupingBy(SealPositionDO::getAccountType));
        List<SealPositionDO> dos = map.get(AccountType.ENTERPRISE.getValue());
        if (!CollectionUtils.isEmpty(dos)) {
            Map<Integer, List<SealPositionDO>> pageMap = dos.stream().collect(Collectors.groupingBy(SealPositionDO::getSealPage));
            List<PositionVO> positionList = new ArrayList<>();
            pageMap.forEach((page, positions) -> {
                PositionVO positionVO = new PositionVO();
                positionVO.setPage(page - 1);
                List<PositionVO.Chapte> chaptes = positions.stream().map(position -> {
                    PositionVO.Chapte chapte = new PositionVO.Chapte();
                    //  处理坐标
                    chapte.setOffsetX(Double.parseDouble(position.getSealPositionX()));
                    chapte.setOffsetY(Double.parseDouble(position.getSealPositionY()));
                    return chapte;
                }).collect(Collectors.toList());
                positionVO.setChaptes(chaptes);
                positionList.add(positionVO);
            });
            sign.setChapteJson(JsonKit.toJSONString(positionList));
        }
        vo.setSignatories(JSON.toJSONString(Collections.singletonList(sign)));
        String url = junZiQianProperties.getServicesUrl() + JunZiQianConstants.URL_CONTRACT_SIGN_ADD;
        JunZiQianUtil.send(vo, junZiQianProperties, url);
    }
}
